<template>
  <div
    class="demo-drawer__content"
    :style="{ '--theme-color': systemInfo.theme }"
  >
    <el-form
      ref="componentFrom"
      :model="form"
      label-width="70px"
      :disabled="isDisabled"
    >
      <el-form-item label="节点名称">
        <common-input v-model="form.name" placeholder="请输入"></common-input>
      </el-form-item>
      <el-form-item label="请求方式">
        <el-select
          v-model="form.method"
          :popper-append-to-body="false"
          placeholder="请选择"
          filterable
          clearable
          @change="change"
        >
          <el-option label="GET" value="GET"></el-option>
          <el-option label="POST" value="POST"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="URL">
        <common-input
          v-model="form.url"
          placeholder="请输入"
          :maxlength="256"
          @input="resetResult"
        ></common-input>
      </el-form-item>
      <el-form-item label="请求参数" class="item-query">
        <el-radio-group v-model="form.query">
          <el-radio-button label="params"></el-radio-button>
          <el-radio-button
            label="body"
            :disabled="form.method === 'GET'"
          ></el-radio-button>
        </el-radio-group>
        <el-button type="primary" plain @click="addQuery">新增</el-button>
      </el-form-item>
      <el-form-item class="identification-table">
        <el-table class="opera-table-container" :data="form.queryList">
          <el-table-column label="参数名称" align="left">
            <template slot-scope="scope">
              <common-input
                placeholder="请输入"
                v-model="scope.row.name"
                @input="resetResult"
              ></common-input>
            </template>
          </el-table-column>
          <el-table-column label="参数值类型" align="left">
            <template slot-scope="scope">
              <el-select
                v-model="scope.row.paramType"
                :popper-append-to-body="false"
                @change="changeParamType"
                placeholder="请选择"
                filterable
                clearable
              >
                <el-option label="自定义" value="define"></el-option>
                <el-option label="变量" value="variable"></el-option>
              </el-select>
            </template>
          </el-table-column>
          <el-table-column label="值" align="left">
            <template slot-scope="scope">
              <el-select
                v-if="scope.row.paramType === 'variable'"
                v-model="scope.row.value"
                :popper-append-to-body="false"
                placeholder="请选择"
                filterable
                clearable
              >
                <el-option
                  v-for="(item, index) in variable"
                  :label="item.label"
                  :value="item.label"
                  :key="index"
                ></el-option>
              </el-select>
              <common-input
                v-else
                placeholder="请输入"
                v-model="scope.row.value"
                @input="resetResult"
              ></common-input>
            </template>
          </el-table-column>
          <!-- <el-table-column label="描述" align="left">
            <template slot-scope="scope">
              <common-input placeholder="请输入" v-model="scope.row.describe"></common-input>
            </template>
          </el-table-column> -->
          <el-table-column label="操作" align="left" width="80">
            <template slot-scope="scope">
              <el-button type="text" @click="deleteQuery(scope.$index)"
                >删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
    </el-form>
    <el-button type="primary" @click="preview" :loading="preLoading"
      >预览</el-button
    >
    <div class="preview-button">
      <common-group-title title="返回结果" />
      <div class="choose-field" :class="{ active: form.path && isShowJson }">
        <span v-if="form.path && isShowJson"
          >已选择: {{ showFields(form.path) }}</span
        >
        <span v-else>未选择字段</span>
      </div>
    </div>
    <div class="preview-data">
      <el-tabs type="border-card">
        <el-tab-pane label="返回结果">
          <div class="json-view" v-if="isShowJson">
            <common-json-view :json="json"></common-json-view>
          </div>
          <div class="tip-content" v-else>
            <div class="label">请先配置接口并预览成功后，才会显示结果解析</div>
          </div>
        </el-tab-pane>
        <el-tab-pane label="字段解析">
          <common-tree
            v-if="isShowJson"
            :treeData="treeData"
            :isShowFilter="false"
            highlight-current
            default-expand-all
            :expand-on-click-node="false"
            @handleNodeExpand="handleNodeExpand"
            @handleNodeCollapse="handleNodeCollapse"
            isSlot
          >
            <div class="api-input-tree-node-item" slot-scope="{ scope }">
              <div
                class="api-input-tree-node-item-label"
                :style="{
                  opacity:
                    scope.data.type === 'array' && scope.data.isTrue
                      ? ''
                      : '0.7',
                }"
              >
                <span>{{ scope.data.label }}</span>
                <span v-if="scope.data.label" style="margin-right: 4px">:</span>
                <span>{{ scope.data.value }}</span>
              </div>
              <el-checkbox
                v-if="scope.data.type === 'array' && scope.data.isTrue"
                :disabled="isDisabled"
                v-model="scope.data.checked"
                @change="changeChecked(scope.data)"
              ></el-checkbox>
            </div>
          </common-tree>
          <div class="tip-content" v-else>
            <div class="label">请先配置接口并预览成功后，才会显示结果解析</div>
          </div>
        </el-tab-pane>
        <el-tab-pane label="解析预览">
          <el-table
            class="opera-table-container"
            :data="showList"
            v-if="treeData.length && form.path"
          >
            <el-table-column
              label="字段名称"
              prop="label"
              align="left"
              show-overflow-tooltip
            />
            <el-table-column
              label="值"
              prop="value"
              align="left"
              show-overflow-tooltip
            />
          </el-table>
          <div class="tip-content" v-else-if="treeData.length">
            <div class="label">
              请先选择字段解析中的某个字段，才会展示解析预览
            </div>
          </div>
          <div class="tip-content" v-else>
            <div class="label">请先配置接口并预览成功后，才会显示结果解析</div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script>
import { transferApi } from "@/api/screenConfig/dataSet";
import { _deepClone, getObjType, guid } from "@/utils";
import { mapGetters } from "vuex";

export default {
  name: "APIInput",
  props: {
    option: {
      type: Object,
      default: () => {},
    },
    isDisabled: {
      type: Boolean,
      default: () => false,
    }, //是否可编辑
    variableConfig: {
      type: Array,
      default: () => []
    },//变量
    variable: {
      type: Array,
      default: () => []
    },//变量
  },
  data() {
    return {
      form: {
        name: "API接口输入",
        method: "GET",
        url: "",
        query: "params",
        queryList: [],
        path: "",
        authorization: "",
        body: "",
        param: "",
      },
      preLoading: false,
      isShowJson: false,
      json: {}, //返回结果展示json
      treeData: [], //字段解析展示数据
      showList: [], //解析预览展示数据
      isFirst: true, //第一次打开弹窗时调用预览接口
    };
  },
  computed: {
    ...mapGetters(["systemInfo"]),
    getVariablePart() {
      console.log(this.variableConfig);
      return this.variableConfig.reduce((r,c) => {
        if(c.variableType === '局部') r.push(c)
        return r
      }, [])
    },
  },
  watch: {
    option: {
      handler: function (val, newVal) {
        this.form = _deepClone(val);
        this.queryList = _deepClone(val.queryList);
        if (this.form.url && this.form.method && this.isFirst) {
          this.preview();
        }
      },
      deep: true,
      immediate: true,
    },
    form: {
      handler: function (val, newVal) {
        // console.log('form', val)
        this.isFirst = false;
        let complete = val.url !== "" && val.path !== "";
        this.$emit("changeForm", val, complete);
      },
      deep: true,
    },
  },
  methods: {
    /**
     * 选择请求方式
     */
    change() {
      this.resetResult();
    },
    changeParamType(val) {
      if(!val) this.resetResult()
    },
    /**
     * 重置预览结果和字段解析
     */
    resetResult() {
      this.form.path = "";
      this.json = {};
      this.isShowJson = false;
      this.treeData = [];
      this.showList = [];
    },
    /**
     * 新增
     */
    addQuery() {
      this.isFirst = false;
      this.resetResult();
      this.form.queryList.push({
        name: "",
        value: "",
        // describe: ''
      });
    },
    /**
     * 删除参数
     * @param index
     */
    deleteQuery(index) {
      this.form.queryList.splice(index, 1);
      this.resetResult();
    },
    /**
     * 预览
     */
    preview() {
      console.log(this.form.queryList);
      if (!this.form.url)
        return this.$message({ type: "warning", message: "url不能为空" });
      if (
        this.form.queryList.length &&
        !this.form.queryList.every((f) => f.name && f.value && f.paramType)
      ) {
        return this.$message({
          type: "warning",
          message: "请填写完整的参数名称和值",
        });
      }
      this.form.body =
        this.form.query !== "params"
          ? JSON.stringify(
              this.form.queryList.reduce((r, c) => {
                if (c.name) {
                  r[c.name] = c.value;
                }
                return r;
              }, {})
            )
          : "";
      this.form.param =
        this.form.query === "params"
          ? this.form.queryList
              .reduce((r, c) => {
                if (c.name) {
                  r.push(`${c.name}=${c.value}`);
                }
                return r;
              }, [])
              .join("&")
          : "";

      this.preLoading = true;
      this.showList = [];
      this.treeData = [];
      
      this.form.variableConfig = this.getVariablePart
      console.log(this.form);
  
      transferApi(this.form)
        .then((res) => {
          if (res && res.code === 200) {
            this.json = res.data ? res.data : {};
            this.isShowJson = true;
            this.treeData = res.data
              ? this.jsonParse(res.data, null, false, false, this.form.path)
              : [];
          } else {
            this.json = {};
            this.treeDate = [];
            this.$GlobalErrorConfirm("预览失败", res.msg);
          }
        })
        .catch((err) => {
          this.json = {};
          this.treeDate = [];
        })
        .finally(() => (this.preLoading = false));
    },
    /**
     * 接口返回数据转化为树结构展示
     * @param jsonData
     * @param parentPath 节点全路径
     * @param isShowSymbol 是否展示符号
     * @param isHiddenArray 是否展示深层数组数据
     * @param path 选中节点全路径
     * @returns {*[]}
     */
    jsonParse(jsonData, parentPath, isShowSymbol, isHiddenArray, path) {
      let temp = [],
        objType = getObjType(jsonData);
      //判断类型是否是object或者array
      if (objType === "object" || (objType === "array" && jsonData.length)) {
        let data = objType === "array" ? jsonData[0] : jsonData;
        //遍历对象中的每个key
        data &&
          Object.keys(data).forEach((j) => {
            let type = getObjType(data[j]),
              obj = {
                label: j,
                path:
                  parentPath && parentPath.length
                    ? [...parentPath, ...[j]]
                    : [j],
              };
            if (type === "object" || type === "array") {
              //判断是否是数组对象，如果不是，直接展示值
              let isTrue = true;
              if (type === "array" && data[j].length > 0) {
                isTrue = data[j].every(
                  (item) => item && getObjType(item) === "object"
                );
              }
              obj.value = !isTrue
                ? `[${data[j].join(",")}]`
                : type === "object"
                ? "{"
                : isHiddenArray
                ? "[...]"
                : !data[j].length
                ? "[]"
                : "[{";
              obj.type = type;
              //是数组对象或者对象，加上check属性
              if (isTrue) {
                obj.isTrue = data[j].length && !isHiddenArray;
                obj.checked = path && obj.path.join(",") === path;
                //某字段被选中时展示解析预览
                if (obj.checked) {
                  this.showList = this.getData(data[j][0]);
                }
                //只展示第一层的数组数据
                if (!isHiddenArray) {
                  obj.children = this.jsonParse(
                    data[j],
                    obj.path,
                    true,
                    type === "array" && isTrue
                  );
                }
              }
            } else {
              obj.value = data[j];
            }
            temp.push(obj);
          });
        if (isShowSymbol) {
          temp.push({
            label: "",
            value: objType === "array" ? "}]" : "}",
          });
        }
      }
      return temp;
    },
    //获取字段解析预览数据
    getData(data) {
      let temp = [];
      data &&
        Object.keys(data).forEach((j) => {
          let type = getObjType(data[j]);
          if (j) {
            temp.push({
              label: j,
              value:
                type === "object" ? "{}" : type === "array" ? "[]" : data[j],
            });
          }
        });
      return temp;
    },
    /**
     * 节点展开时触发事件
     */
    handleNodeExpand(data) {
      data.data.value = data.data.value.slice(0, data.data.value.length - 5);
    },
    /**
     * 节点关闭时触发事件
     */
    handleNodeCollapse(data) {
      setTimeout(() => {
        data.data.value += "...}]";
      }, 300);
    },
    /**
     * checkbox事件
     * @param info
     */
    changeChecked(info) {
      this.form.path = info.checked ? info.path.join(",") : "";
      //遍历去除其他已选字段
      let setChecked = (arr) => {
        arr.forEach((item) => {
          item.checked =
            item.type === "array" && item.path.join(",") === this.form.path;
          if (item.children && item.children.length) setChecked(item.children);
        });
      };
      setChecked(this.treeData);
      this.showList = info.checked
        ? info.children.reduce((r, c) => {
            if (c.label) {
              r.push({
                ...c,
                value:
                  c.type && c.type === "array"
                    ? "[]"
                    : c.type && c.type === "object"
                    ? "{}"
                    : c.value,
              });
            }
            return r;
          }, [])
        : [];
    },
    showFields(str) {
      let list = str.split(",");
      return list[list.length - 1];
    },

    //自定义校验方法
    checkFormBeforeClose() {
      if (
        this.form.queryList.length &&
        !this.form.queryList.every((f) => f.name && f.value && f.paramType)
      ) {
        return this.$message({
          type: "warning",
          message: "请填写完整的参数名称和值",
        });
      }
      return "ok";
    },
  },
};
</script>

<style scoped lang="scss">
.demo-drawer__content {
  padding: 0 16px 16px 16px;
  overflow-y: scroll;

  .preview-data {
    margin-top: 12px;
  }

  .el-form {
    .form-item-flex {
      display: flex;
      justify-content: space-between;

      .el-select {
        width: 49%;
      }
    }

    .item-query {
      ::v-deep .el-form-item__content {
        display: flex;
        justify-content: space-between;

        &:before,
        &:after {
          content: none;
        }
      }
    }

    ::v-deep
      .el-form-item.is-required:not(.is-no-asterisk)
      > .el-form-item__label:before {
      content: "";
    }
  }

  .el-tabs {
    margin-top: 12px;
  }
}

.identification-table {
  ::v-deep .el-form-item__content {
    margin-left: 20px !important;
  }
}

.opera-table-container {
  margin-top: 0;
}

::v-deep .api-input-tree-node-item {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;

  .api-input-tree-node-item-label {
    width: 100%;
    display: flex;
    justify-content: flex-start;
    align-items: center;
  }
}

.preview-button {
  display: flex;
  align-items: center;
  margin-top: 8px;
  font-size: 14px;

  .choose-field {
    border: 1px solid #bbb;
    padding: 4px 12px;
    font-size: 12px;
    color: #606266;
    border-radius: 3px;
    margin: 0 8px;
    font-weight: 500;
  }

  .active {
    border-color: var(--theme-color) !important;
    color: var(--theme-color) !important;
  }
}

.tip-content {
  font-size: 14px;
  padding: 12px;
  display: flex;
  align-items: center;
  justify-content: center;

  .label {
    padding: 6px 16px;
    background: rgba(255, 144, 62, 0.1);
    color: rgba(255, 144, 62, 1);
    border: 1px dashed rgba(255, 144, 62, 1);
    border-radius: 4px;
  }
}
</style>